package com.spark.demoim.utils

import android.os.Handler
import android.os.Looper
import android.os.Process
import java.util.concurrent.*
import kotlin.system.exitProcess

/**
 * Created by lenovo on 2017/8/15.
 */
/**
 * 优先级 ThreadFactory
 */
open class PriorityThreadFactory(val threadPriority: Int) : ThreadFactory {
    override fun newThread(task: Runnable): Thread {
        val wrapRunnable = Runnable {
            run {
                try {
                    Process.setThreadPriority(threadPriority)
                } catch (t: Throwable) {
                    t.printStackTrace()
                }
            }
            task.run()
        }
        return Thread(wrapRunnable)
    }
}

/**
 * UI 线程执行 Runnable
 */
open class UIThreadExector : Executor {
    private val handler = Handler(Looper.getMainLooper())
    override fun execute(task: Runnable) {
        handler.post(task)
    }
}

open class TaskProvider {
    companion object {
        val instance: TaskProvider by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { TaskProvider() }
        // 核心线程数等于 CPU 的核数
        val NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors()
    }

    var backgroundTask: ThreadPoolExecutor? = null
    var mainThreadExecutor: Executor? = null

    init {
        // 设置工厂
        val priorityThreadFactory = PriorityThreadFactory(Process.THREAD_PRIORITY_BACKGROUND)
        backgroundTask = ThreadPoolExecutor(
                NUMBER_OF_CORES * 2,
                NUMBER_OF_CORES * 2,
                60L,
                TimeUnit.SECONDS,
                LinkedBlockingQueue<Runnable>(),
                priorityThreadFactory)
        mainThreadExecutor = UIThreadExector()

    }

    fun backTask(): ThreadPoolExecutor {
        return backgroundTask!!
    }

    fun uiTask(): Executor {
        return mainThreadExecutor!!
    }

    fun backTask(task: Runnable.() -> Unit) {
        backgroundTask!!.execute { task }
    }

    fun uiTask(task: Runnable.() -> Unit) {
        mainThreadExecutor!!.execute { task }
    }

    fun backTaskWithResult(task: Runnable.() -> Unit): Future<*> {
        return backgroundTask!!.submit { task }
    }

}